// Includes
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <limits.h>

#include <iostream>
#include <string>

#include <ctime>
#include <cstdlib>

//Incluyo la clase global.cpp  que contiene las variables y funciones globales
#include "../utils/global.cpp"

//Incluyo la clase mt.cpp para valores aleatorios
#include "../utils/mt.cpp"

using namespace std;


/****************** Representacion real ********************/

/******************* Declaracion de Funciones del Host *************************/
void representacionReal();

/******************* Declaracion de Funciones Global del  ********************/
 void inicializarPoblacionReal(float* poblacion, float* fitnessActual, MersenneTwister *mt, int cantCromosomasPoblacion, int ejecutarFuncion);
 void mainKernelReal(float* poblacionActual, float* nuevaPoblacion, float* fitnessActual, float* nuevoFitness, float* individuosAMigrar, MersenneTwister *mt, int generacionActual, int nroPoblacion, int posActual);

/******************* Declaracion de Funciones internas del  *****************/
 int seleccionReal(float* vectorFitness, MersenneTwister *mt, int ejecutarFuncion, int indiceMejor, int nroPoblacion, int posActual);
 int seleccionPorTorneoReal(float* vectorFitness, MersenneTwister *mt, int nroPoblacion, int posActual);
 int seleccionElitistaReal(float* vectorFitness, int indiceMejor, int nroPoblacion, int posActual);

 void cruzamientoRepresentacionReal(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual);
 void cruzamientoAritmetico(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
 void cruzamientoAritmeticoIndividual(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
 void cruzamientoAritmeticoSimple(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
 void cruzamientoAritmeticoCompleto(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);

 void mutacionReal(float* poblacion, int probabilidad, MersenneTwister *mt, int ejecutarFuncion, int generacionActual, int nroPoblacion, int posActual);
 void mutacionUniforme(float* poblacion, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
 void mutacionNoUniforme(float* poblacion, int probabilidad, MersenneTwister *mt, int generacionActual, int nroPoblacion, int posActual);

 void asignarFitnessReal(float* poblacion, float* vectorFitness, int nroPoblacion, int posActual);
 float calcularFitnessReal(float* poblacion, int posicion);

/******************* Implementacion de Funciones del  *****************/


 void inicializarPoblacionReal(float* poblacion, float* fitnessActual, MersenneTwister *mt, int cantCromosomasPoblacion, int ejecutarFuncion){
	//Obtengo posicion a escribir.
	int posicionCromosoma = 0;
	int posicionFitness = 0;
	for(int i = 0; i < cantidadPoblaciones * cantCromosomasPoblacion; i++){
		//Genero valor aleatorio.
		float r = (mt->genrand_real1())/1000;
		poblacion[posicionCromosoma+i] = r;
	}

	for(int i = 0; i< cantidadPoblaciones * cantCromosomasPoblacion; i++){
		fitnessActual[posicionFitness] = calcularFitnessReal(poblacion, posicionCromosoma);
		posicionFitness++;
		posicionCromosoma = posicionCromosoma + cantGenesEnCromosoma;
	}
}


 void mainKernelReal(float* poblacionActual, float* nuevaPoblacion, float* fitnessActual, float* nuevoFitness, float* individuosAMigrar, MersenneTwister *mt, int generacionActual, int nroPoblacion, int posActual){
	//genero numero aleatorio entre 0 y cant individuos por poblacion
	int posicionCromosoma1 = seleccionReal(fitnessActual, mt, tipoSeleccion, 1, nroPoblacion, posActual);
	int posicionCromosoma2 = seleccionReal(fitnessActual, mt, tipoSeleccion, 2, nroPoblacion, posActual);
	cruzamientoRepresentacionReal(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidadCruzamiento, mt, tipoCruzamiento, nroPoblacion, posActual);

	mutacionReal(nuevaPoblacion, probabilidadMutacion, mt, tipoMutacion, generacionActual, nroPoblacion, posActual);
	//asignarFitness(nuevaPoblacion, nuevoFitness);

	//__syncthreads();
	//if (threadIdx.x == 0) {
	///	individosAMigrarRepresentacionBinaria(nuevoFitness, nuevaPoblacion, individuosAMigrar);
	//}
}


/******************* Implementacion de Funciones de Migracion *****************/




/******************* Implementacion de Funciones de Selecccion *****************/

 int seleccionReal(float* vectorFitness, MersenneTwister *mt, int ejecutarFuncion, int indiceMejor, int nroPoblacion, int posActual){
	int resultado = -1;
	if(ejecutarFuncion == 0) {
		resultado = seleccionElitistaReal(vectorFitness, indiceMejor, nroPoblacion, posActual);
	}
	else if(ejecutarFuncion == 1) {
		resultado = seleccionPorTorneoReal(vectorFitness, mt, nroPoblacion, posActual);
	}
	return resultado;
}


//Seleccion elitista
//selecciona el mejor o segundo mejor elemento segun se indica en indiceMejor con un 1 o con un 2
 int seleccionElitistaReal(float* vectorFitness, int indiceMejor, int nroPoblacion, int posActual){
	printf("*** Seleccion elitista real ***\n");
	int mejor1 = -1;
	int mejor2 = -2;
	int indiceMejor1, indiceMejor2;
	float valorFitness;
	int indiceMemoria = nroPoblacion * cantCromosomasPoblacion;
	for(int i = 0; i< cantCromosomasPoblacion; i++){
		valorFitness = vectorFitness[indiceMemoria + i];
		if (valorFitness > mejor1) {
			mejor2 = mejor1;
			indiceMejor2 = indiceMejor1;
			mejor1 = valorFitness;
			indiceMejor1 = i;
		}
		else {
			if (valorFitness > mejor2){
				mejor2 = valorFitness;
				indiceMejor2 = i;
			}
		}
	}
	int posicionCromosomaMejor1 = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + indiceMejor1 * cantGenesEnCromosoma;
	int posicionCromosomaMejor2 = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + indiceMejor2 * cantGenesEnCromosoma;
	if (indiceMejor == 1) {
		return posicionCromosomaMejor1;
	}
	return posicionCromosomaMejor2;
}

//Seleccion por torneo
//selecciona 2 individuos al azar y devuelve la posicion del mejor
 int seleccionPorTorneoReal(float* vectorFitness, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Seleccion por torneo real ***\n");
	unsigned int r = (mt->genrand_int32()) % cantCromosomasPoblacion;
	int posicionFitnessAleatoria1 = nroPoblacion * cantCromosomasPoblacion + r;
	int posicionCromosomaAleatoria1 = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + r * cantGenesEnCromosoma;
	r = (mt->genrand_int32() + 1)% cantCromosomasPoblacion;
	int posicionFitnessAleatoria2 = nroPoblacion * cantCromosomasPoblacion + r;
	int posicionCromosomaAleatoria2 = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + r * cantGenesEnCromosoma;
	if (vectorFitness[posicionFitnessAleatoria1] > vectorFitness[posicionFitnessAleatoria2])
		return posicionCromosomaAleatoria1;
	return posicionCromosomaAleatoria2;
}



/******************* Implementacion de Funciones de Cruzamiento *****************/

 void cruzamientoRepresentacionReal(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual){

	if(ejecutarFuncion == 0) {
		cruzamientoAritmetico(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidad, mt, nroPoblacion, posActual);
	}
	else{
		if(ejecutarFuncion == 1){
			cruzamientoAritmeticoIndividual(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidad, mt, nroPoblacion, posActual);
		}
		else {
			if(ejecutarFuncion == 2) {
				cruzamientoAritmeticoSimple(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidad, mt, nroPoblacion, posActual);
			}
			else {
				if(ejecutarFuncion == 3) {
					cruzamientoAritmeticoCompleto(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidad, mt, nroPoblacion, posActual);
				}
			}
		}
	}
}


 void cruzamientoAritmetico(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Cruzamiento Aritmetico ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;

	unsigned int prob;
	float alfa = fmod((mt->genrand_int32()), 1);
	printf("alfa = %f", alfa);
	prob = ((mt->genrand_int32()) % 101);
	if(prob < probabilidad ){
		for(int i=0; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = alfa * poblacionActual[posicionCromosoma1 + i] + (1-alfa) * poblacionActual[posicionCromosoma2 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = alfa * poblacionActual[posicionCromosoma2 + i] + (1-alfa) * poblacionActual[posicionCromosoma1 + i];
		}
	}else{
		for(int i=0; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
		}
	}
}

 void cruzamientoAritmeticoIndividual(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Cruzamiento Aritmetico Individual ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;

	unsigned int prob;
	int genAcruzar = ((mt->genrand_int32()) % cantGenesEnCromosoma);
	prob = ((mt->genrand_int32()) % 101);
	for(int i=0; i<cantGenesEnCromosoma; i++){
		nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
		nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
		if((i == genAcruzar) && (prob < probabilidad)){
			float alfa = fmod((mt->genrand_int32()), 1);
			printf("alfa = %f", alfa);
			nuevaPoblacion[posicionNuevoCromosoma1+i] = alfa * poblacionActual[posicionCromosoma1 + i] + (1-alfa) * poblacionActual[posicionCromosoma2 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = alfa * poblacionActual[posicionCromosoma2 + i] + (1-alfa) * poblacionActual[posicionCromosoma1 + i];
		}
	}
}

 void cruzamientoAritmeticoSimple(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Cruzamiento Aritmetico Simple ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;

	unsigned int prob;
	unsigned int k = ((mt->genrand_int32()) % cantGenesEnCromosoma);
	printf("k = %d", k);
	float alfa = fmod((mt->genrand_int32()), 1);
	printf(" alfa = %f\n", alfa);
	for(int i=0; i<k; i++){
		nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
		nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
	}
	prob = ((mt->genrand_int32()) % 101);
	if(prob < probabilidad ){
		for(int i=k; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = alfa * poblacionActual[posicionCromosoma2 + i] + (1-alfa) * poblacionActual[posicionCromosoma1 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = alfa * poblacionActual[posicionCromosoma1 + i] + (1-alfa) * poblacionActual[posicionCromosoma2 + i];
		}
	}else{
		for(int i=k; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
		}
	}
}

 void cruzamientoAritmeticoCompleto(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Cruzamiento Aritmetico Completo ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;

	unsigned int prob = ((mt->genrand_int32()) % 101);
	float alfa = fmod((mt->genrand_int32()), 1);
	printf(" alfa = %f\n", alfa);
	if(prob < probabilidad ){
		for(int i=0; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = alfa * poblacionActual[posicionCromosoma1 + i] + (1-alfa) * poblacionActual[posicionCromosoma2 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = alfa * poblacionActual[posicionCromosoma2 + i] + (1-alfa) * poblacionActual[posicionCromosoma1 + i];
		}
	}else{
		for(int i=0; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
		}
	}
}


/******************* Implementacion de Funciones de Mutacion *****************/


 void mutacionReal(float* poblacion, int probabilidad, MersenneTwister *mt, int ejecutarFuncion, int generacionActual, int nroPoblacion, int posActual){

	if(ejecutarFuncion == 0) {
		mutacionUniforme(poblacion, probabilidad, mt, nroPoblacion, posActual);
	}
	else{
		if(ejecutarFuncion == 1){
			mutacionNoUniforme(poblacion, probabilidad, mt, generacionActual, nroPoblacion, posActual);
		}
	}
}


 void mutacionUniforme(float* poblacion, int probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Mutacion uniforme real ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;

	unsigned int k;
	float left_k, right_k, aux1;
	float aux;
	unsigned int prob = ((mt->genrand_int32()) % 101);
	if (prob < probabilidad ){
		k = (mt->genrand_int32() + 1) % cantGenesEnCromosoma;
		//printf("k = %d \n",k);
		left_k = poblacion[posicionNuevoCromosoma1 + (k - 1) % cantGenesEnCromosoma];
		right_k = poblacion[posicionNuevoCromosoma1 + (k + 1) % cantGenesEnCromosoma];
		aux = (mt->genrand_int32());
		//printf("aux = %f \n",aux);
		if (left_k > right_k){
			aux1 = right_k;
			right_k = left_k;
			left_k = aux1;
		}
		poblacion[posicionNuevoCromosoma1 + k] = left_k + aux * (right_k - left_k);
	}

	prob = ((mt->genrand_int32()) % 101);
	if (prob < probabilidad ){
		k = (mt->genrand_int32() + 1) % cantGenesEnCromosoma;
		//printf("- individuo 2  -\n k = %d \n",k);
		left_k = poblacion[posicionNuevoCromosoma2 + (k - 1) % cantGenesEnCromosoma];
		right_k = poblacion[posicionNuevoCromosoma2 + (k + 1) % cantGenesEnCromosoma];
		aux = (mt->genrand_int32());
		//printf("aux = %f \n",aux);
		if (left_k > right_k){
			aux1 = right_k;
			right_k = left_k;
			left_k = aux1;
		}
		poblacion[posicionNuevoCromosoma2 + k] = left_k + aux * (right_k - left_k);
	}
}

 void mutacionNoUniforme(float* poblacion, int probabilidad, MersenneTwister *mt, int generacionActual, int nroPoblacion, int posActual){
	printf("*** Mutacion no uniforme real ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;

	unsigned int k;
	float left_k, right_k, resultado, r;
	int aux;
	unsigned int prob = ((mt->genrand_int32()) % 101);
	if (prob < probabilidad ){
		k = (mt->genrand_int32() + 1) % cantGenesEnCromosoma;
		printf("k = %d \n",k);
		left_k = poblacion[posicionNuevoCromosoma1 + ((k - 1) % cantGenesEnCromosoma)];
		right_k = poblacion[posicionNuevoCromosoma1 + ((k + 1) % cantGenesEnCromosoma)];
		aux = (mt->genrand_int32()) % 1;
		printf("aux = %d \n",aux);
		r = (mt->genrand_int32());
		if (aux == 0){
		/*	printf("generacionActual = %d \n", generacionActual);
			printf("numeroGeneraciones = %d\n", numeroGeneraciones);
			printf("r = %f\n", r);
			printf("pow = %f\n", __powf((1 - (generacionActual/numeroGeneraciones)), gradoNoUniformidad));
		*/
			resultado = poblacion[posicionNuevoCromosoma1 + k] + ((right_k - poblacion[posicionNuevoCromosoma1 + k]) * r * (pow((1 - (generacionActual/numeroGeneraciones)), gradoNoUniformidad)));
		}
		else {
		/*	printf("generacionActual = %d \n", generacionActual);
			printf("numeroGeneraciones = %d\n", numeroGeneraciones);
			printf("r = %f\n", r);
			printf("pow = %f\n", __powf((1 - (generacionActual/numeroGeneraciones)), gradoNoUniformidad));
		*/
			resultado = poblacion[posicionNuevoCromosoma1 + k] - ((poblacion[posicionNuevoCromosoma1 + k] - left_k) * r * (pow((1 - (generacionActual/numeroGeneraciones)), gradoNoUniformidad)));
		}
		poblacion[posicionNuevoCromosoma1 + k] = resultado;
	}

	prob = ((mt->genrand_int32()) % 101);
	if (prob < probabilidad ){
		k = (mt->genrand_int32() + 1) % cantGenesEnCromosoma;
		printf("k = %d \n",k);
		left_k = poblacion[posicionNuevoCromosoma2 + ((k - 1) % cantGenesEnCromosoma)];
		right_k = poblacion[posicionNuevoCromosoma2 + ((k + 1) % cantGenesEnCromosoma)];
		aux = (mt->genrand_int32()) % 1;
		printf("aux = %d \n",aux);
		r = (mt->genrand_int32());
		if (aux == 0){
			resultado = poblacion[posicionNuevoCromosoma2 + k] + ((right_k - poblacion[posicionNuevoCromosoma2 + k]) * r * (pow((1 - (generacionActual/numeroGeneraciones)), gradoNoUniformidad)));
		}
		else {
			resultado = poblacion[posicionNuevoCromosoma2 + k] - ((poblacion[posicionNuevoCromosoma2 + k] - left_k) * r * (pow((1 - (generacionActual/numeroGeneraciones)), gradoNoUniformidad)));
		}
		poblacion[posicionNuevoCromosoma2 + k] = resultado;
	}
}

/******************* Implementacion de Funciones de fitness *****************/

 void asignarFitnessReal(float* nuevaPoblacion, float* nuevoVectorFitness, int nroPoblacion, int posActual){
	//Obtengo posicion del primer cromosoma.
	int posicionCromosoma = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionFitness = posActual * 2 + nroPoblacion * cantCromosomasPoblacion;
	nuevoVectorFitness[posicionFitness] = calcularFitnessReal(nuevaPoblacion, posicionCromosoma);
	nuevoVectorFitness[posicionFitness + 1] = calcularFitnessReal(nuevaPoblacion, posicionCromosoma + cantGenesEnCromosoma);
}


 float calcularFitnessReal(float* poblacion, int posicion) {
	float fitness = 0;
	float contador = cantGenesEnCromosoma-1;
	for(int i=0; i<cantGenesEnCromosoma; i++){
	  fitness = fitness + poblacion[posicion + i];
	  contador--;
	}
	return fitness;
}

/******************* Implementacion de Funciones del host *****************/


void representacionReal() {
	int tamVectorPoblacion = sizeof(float)*totalGenes;
	int tamVectorFitness = sizeof(float)*totalIndividuos;
	int tamVectorIndividuosAMigrar = sizeof(float)*cantGenesEnCromosoma*cantidadPoblaciones;

	static float *poblacionActualHost = (float *) malloc(tamVectorPoblacion);
	static float *nuevaPoblacionHost = (float *) malloc(tamVectorPoblacion);
	static float *fitnessActualHost = (float *) malloc(tamVectorFitness);
	static float *nuevoFitnessHost = (float *) malloc(tamVectorFitness);
	static float *individuosAMigrarHost = (float *) malloc(tamVectorIndividuosAMigrar);

	//inicializo la clase mt para las variables aleatorias
	MersenneTwister* mt;

	//Inicio numeros aleatorios.
	mt = new MersenneTwister();
	mt->init_genrand(time(NULL));

	//inicializacion de la poblacion en GPU
	inicializarPoblacionReal(poblacionActualHost, fitnessActualHost, mt, cantCromosomasPoblacion, 2);

	cout << "tot " << totalGenes << " POBLACION INICIAL\n";
	cout << totalGenes;
	for (int i = 0; i<totalGenes; i++){
		if(i%cantGenesEnCromosoma == 0){
			cout << "\n";

		}
		printf("%f ", poblacionActualHost[i]);
	}
	cout << "\n\n\nFITNESS\n";

	for (int i = 0; i<cantCromosomasPoblacion * cantidadPoblaciones; i++){
		printf("%f ", fitnessActualHost[i]);
	}
	cout << "\n\n\n\n";

	int nroPoblacion;
		int iteracion = 0;
		//los individuos de la poblacion actual se van intercambiando en el reemplazo
		while(iteracion < numeroGeneraciones){
			nroPoblacion = 0;
			for (int i = 0; i < cantidadPoblaciones*cantCromosomasPoblacion/2; i++){
				nroPoblacion = i/(cantCromosomasPoblacion/2);
				//si la iteracion es par invoco a GPU con poblacionActual, nuevaPoblacion
				if ((iteracion % 2) == 0) {
					// seleccionamos, cruzamos y mutamos en GPU
					mainKernelReal(poblacionActualHost, nuevaPoblacionHost, fitnessActualHost, nuevoFitnessHost, individuosAMigrarHost, mt, iteracion, nroPoblacion, i%(cantCromosomasPoblacion/2));

					//Si hay que migrar
					//if (iteracion % generacionesMigrar == 0) {
					//	migracionRepresentacionBinaria<<<tamGrid, tamBlockMigracion>>>(nuevaPoblacion, nuevoFitness, individuosAMigrar, r, iteracion);
					//}
				}
				//sino invoco a GPU con nuevaPoblacion, poblacionActual
				else {

					// seleccionamos, cruzamos y mutamos en GPU
					mainKernelReal(nuevaPoblacionHost, poblacionActualHost, nuevoFitnessHost, fitnessActualHost, individuosAMigrarHost, mt, iteracion, nroPoblacion, i%(cantCromosomasPoblacion/2));

					//Si hay que migrar
					//if (iteracion % generacionesMigrar == 0) {
					//	migracionRepresentacionBinaria<<<tamGrid, tamBlockMigracion>>>(poblacionActual, fitnessActual, individuosAMigrar, r);
					//}
				}
			}
		//mejorFitness = obtenerMejorFitness(poblacionActual,mejorCromosoma);
		iteracion++;
	}


	cout << "NUEVA POBLACION\n";
	for (int i = 0; i<totalGenes; i++){
		if(i%cantGenesEnCromosoma == 0){
			cout << "\n";

		}
		printf("%f ", nuevaPoblacionHost[i]);
	}
	cout << "\n\n\nFITNESS\n";

	for (int i = 0; i<cantCromosomasPoblacion * cantidadPoblaciones; i++){
		printf("%f ", nuevoFitnessHost[i]);
	}
	cout << "\n";

	/*cout << "\n\nA MIGRAR\n";

	for (int i = 0; i<cantGenesEnCromosoma * cantidadPoblaciones; i++){
		if(i%cantGenesEnCromosoma == 0){
			cout << "\n";
		}
		printf("%i ", individuosAMigrarHost[i]);
	}
	cout << "\n";
	*/
}

